﻿#include <cstdio>
#include <string.h>
#include <string>
#include <iostream>
#include <stdio.h>
#include <unistd.h>
#include <sstream>
#include <iomanip>

#include <openssl/hmac.h>
#include <openssl/md5.h>

#define MD5_SIZE                    16

std::string GetCurrentDateHours2Str(const time_t t)
{
    char date[15] = { 0 };

    try
    {
        strftime(date, sizeof(date), "%Y%m%d%H", localtime(&t)); //年月日
    }
    catch (...)
    {
        for (int i = 0; i < 10; i++)
        {
            date[i] = { 0 };
        }
    }

    return date;
}


int Md5(const char* data, char* outChr)
{

    unsigned char md5Value[MD5_SIZE];

    MD5_CTX ctx;
    MD5_Init(&ctx); //Init ctx

    MD5_Update(&ctx, data, (unsigned int)strlen(reinterpret_cast<const char*>(data)));
    MD5_Final(md5Value, &ctx);

    for (int i = 0; i < MD5_SIZE; i++)
    {
        snprintf(outChr + i * 2, 2 + 1, "%02x", md5Value[i]);
    }

    return 0;
}

std::string HmacSha256(std::string key, const char* input)
{
    unsigned int outputLen = EVP_MAX_MD_SIZE;
    unsigned char output[EVP_MAX_MD_SIZE];
#if !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x10100000L

    HMAC_CTX ctx;
    HMAC_CTX_init(&ctx);
    HMAC_Init_ex(&ctx, key.c_str(), key.length(), EVP_sha256(), NULL);
    HMAC_Update(&ctx, (unsigned char*)input, strlen(input));

    HMAC_Final(&ctx, output, &outputLen);
    HMAC_CTX_cleanup(&ctx);

#else
    HMAC_CTX* ctx;
    ctx = HMAC_CTX_new();
    HMAC_Init_ex(ctx, key.c_str(), key.length(), EVP_sha256(), NULL);
    HMAC_Update(ctx, (unsigned char*)input, strlen(input));

    HMAC_Final(ctx, output, &outputLen);
    HMAC_CTX_free(ctx);
#endif

    std::stringstream hmacShaStr;
    for (unsigned int i = 0; i < outputLen; i++)
    {
        hmacShaStr << std::hex << std::setw(2) << std::setfill('0') << (unsigned int)output[i];
    }
    return hmacShaStr.str();
}

int main()
{

    std::string token = "2900003";
    std::string productId = "audiotest";
    std::string deviceId = "";

    deviceId.append(productId);
    deviceId.append("_");
    deviceId.append(token);

    const time_t t = time(NULL);

    std::string timeStr = GetCurrentDateHours2Str(t);

    std::string clientdId = "";
    clientdId.append(deviceId);
    clientdId.append("_0_0_");
    clientdId.append(timeStr);

    char password[32 + 1] = { 0 };
    Md5(token.c_str(), password);

    printf("token: %s\n", token.c_str());
    printf("productId: %s\n", productId.c_str());
    printf("clientdId: %s\n", clientdId.c_str());
    printf("deviceId: %s\n", deviceId.c_str());
    printf("timeStr: %s\n", timeStr.c_str());
    printf("password: %s\n", password);

    std::string hmacPassword = "";
    hmacPassword = HmacSha256(timeStr, password);
    printf("hmacPassword: %s\n", hmacPassword.c_str());


    return 0;
}